// stores/websocketStore.ts
import {defineStore} from 'pinia'
import {ref, onUnmounted, onMounted} from 'vue'
import {message, notificationBox} from "@/utils/ElmessasgeUtils"
import {getUserInfo} from "@/utils/system"
import type {WebSocketDataBody} from "@/type/common/websocketType";
import {WEBSOCKET_MESSAGE_TYPE} from "@/enum/admin/WebSocketDataTypeEnum";
import router from "@/router";


// 定义消息处理器类型
type MessageHandler = (payload: WebSocketDataBody) => void

export const useWebSocketStore = defineStore('websocket', () => {
    const isConnected = ref(false)
    const serverTime = ref<Date | null>(null)
    const ws = ref<WebSocket | null>(null)
    const reconnectAttempts = ref(0)
    const maxReconnectAttempts = 5
    const reconnectInterval = ref(3000) // 3秒
    let reconnectTimer: any = null
    let url = 'ws://' + location.host + '/Admin/global-connect'


    // 存储所有消息处理器
    const messageHandlers = new Map<number, MessageHandler[]>()
    // 注册消息处理器
    const onMessage = (messageType: number, handler: MessageHandler): void => {
        if (!messageHandlers.has(messageType)) {
            messageHandlers.set(messageType, [])
        }
        messageHandlers.get(messageType)!.push(handler)
    }

    // 注销消息处理器
    const offMessage = (messageType: number, handler?: MessageHandler): void => {
        if (!handler) {
            // 如果不指定handler，移除该类型的所有处理器
            messageHandlers.delete(messageType)
        } else {
            const handlers = messageHandlers.get(messageType)
            if (handlers) {
                const index = handlers.indexOf(handler)
                if (index > -1) {
                    handlers.splice(index, 1)
                }
                if (handlers.length === 0) {
                    messageHandlers.delete(messageType)
                }
            }
        }
    }

    // 触发消息处理器
    const triggerMessageHandlers = (payload: WebSocketDataBody): void => {
        const handlers = messageHandlers.get(payload.type) || []
        handlers.forEach(handler => {
            try {
                handler(payload)
            } catch (error) {
                console.error(`消息类型 ${payload.type} 处理器执行错误:`, error)
            }
        })
    }

    const connect = async () => {
        if (!url) {
            console.error('WebSocket URL 未设置')
            return
        }
        if (!getUserInfo().username) {
            await router.push('/login')
            return
        }
        try {
            ws.value = new WebSocket(url + '?username=' + getUserInfo().username)
            isConnected.value = true
            reconnectAttempts.value = 0
            reconnectInterval.value = 3000

            ws.value.onopen = () => {
                let msg = {
                    type: 0,
                    fromUserId: getUserInfo().userId,
                    fromUserName: getUserInfo().username,
                }

                let sendConnectedMessage = JSON.stringify(msg)
                // 发送上线消息
                if (ws.value) {
                    ws.value.send(sendConnectedMessage)
                }
            }

            ws.value.onmessage = (event: MessageEvent) => {
                try {
                    const payload: WebSocketDataBody = JSON.parse(event.data)
                    console.log("收到后台消息", payload)

                    // 触发所有注册的消息处理器
                    triggerMessageHandlers(payload)

                    handleDefaultMessage(payload)

                } catch (error) {
                    console.error('消息解析错误:', error)
                }
            }

            ws.value.onclose = (event: CloseEvent) => {
                console.log('WebSocket连接关闭:', event.code, event.reason)
                isConnected.value = false
                attemptReconnect()
            }

            ws.value.onerror = (error: Event) => {
                console.error('WebSocket错误:', error)
                isConnected.value = false
            }

        } catch (error) {
            console.error('WebSocket连接失败:', error)
            attemptReconnect()
        }
    }

    // 原有的默认消息处理逻辑
    const handleDefaultMessage = (payload: WebSocketDataBody): void => {
        const msgType = payload.type

        // 用户上线
        if (msgType == WEBSOCKET_MESSAGE_TYPE.USER_ONLINE) {
            notificationBox("用户：" + payload.fromUserName + "上线了", "系统提示")
        } else if (msgType == WEBSOCKET_MESSAGE_TYPE.USER_OFFLINE) {
            notificationBox("用户：" + payload.fromUserName + "下线了", "系统提示", 3000, 'error')
        }

        // 转发的其他用户 广播 发送的消息体
        if (payload.toUserId == "-1") {
            notificationBox(payload.msg, "收到" + payload.fromUserName + "广播的消息")
        }
        // 转发的其他用户  单独发送 的消息体
        if (payload.toUserId == getUserInfo().userId) {
            notificationBox(payload.msg, "收到" + payload.fromUserName + "发来的消息")
        }

    }

    const attemptReconnect = (): void => {
        if (reconnectAttempts.value < maxReconnectAttempts) {
            reconnectAttempts.value = reconnectAttempts.value + 1
            console.log(`尝试重新连接... (${reconnectAttempts.value}/${maxReconnectAttempts})`)

            reconnectTimer = setTimeout(async () => {
                await connect()
            }, reconnectInterval.value)

            // 指数退避策略
            reconnectInterval.value = Math.min(reconnectInterval.value * 1.5, 30000)
        } else {
            console.error('达到最大重连次数，停止重连')
        }
    }

    const disconnect = async () => {
        if (reconnectTimer) {
            clearTimeout(reconnectTimer)
            reconnectTimer = null
        }

        if (ws.value) {
            ws.value.close(1000, '正常关闭')
            ws.value = null
        }

        isConnected.value = false
    }

    const sendMessage = (msg: WebSocketDataBody): void => {
        if (ws.value && isConnected.value) {
            ws.value.send(JSON.stringify(msg))
        } else {
            console.error('WebSocket 未连接，无法发送消息')
        }
    }

    // 清理函数
    const cleanup = async () => {
        await disconnect()
    }

    return {
        isConnected,
        serverTime,
        connect,
        disconnect,
        sendMessage,
        onMessage,
        offMessage,
        cleanup
    }
})